import tensorflow as tf
import numpy as np
import pandas as pd

def load_data():
    """加载商品房销售记录表数据"""
    encodings = ['gbk', 'gb18030', 'gb2312', 'utf-8']
    for encoding in encodings:
        try:
            # 读取文件时不指定列名
            data = pd.read_csv('data.csv', header=None, encoding=encoding)
            print(f"成功使用{encoding}编码加载数据")
            
            # 从第3行开始读取数据（跳过标题行和列名行）
            # 每行包含两套房子的信息，需要重新组织数据
            rows = []
            for _, row in data.iloc[2:].iterrows():
                # 第一套房子：编号、面积、房间数、价格
                rows.append([row[0], row[1], row[2], row[3]])
                # 第二套房子：编号、面积、房间数、价格
                rows.append([row[4], row[5], row[6], row[7]])
            
            # 创建新的DataFrame，并给列命名
            formatted_data = pd.DataFrame(rows, columns=['编号', '面积', '房间数', '价格'])
            return formatted_data
            
        except UnicodeDecodeError:
            continue
        except FileNotFoundError:
            print("错误：找不到data.csv文件，请确保文件在正确的位置")
            return None
        except Exception as e:
            print(f"加载数据时出错: {e}")
            return None
    
    print("尝试了多种编码方式，但仍无法加载文件。请检查文件编码或内容是否损坏。")
    return None

def build_model(data):
    """使用TensorFlow构建线性回归模型"""
    # 确保数据是数值类型
    data['面积'] = pd.to_numeric(data['面积'].str.strip(), errors='coerce')
    data['房间数'] = pd.to_numeric(data['房间数'].str.strip(), errors='coerce')
    data['价格'] = pd.to_numeric(data['价格'].str.strip(), errors='coerce')
    
    # 删除缺失值
    data = data.dropna()
    
    # 提取特征和标签
    X = data[['面积', '房间数']].values
    y = data['价格'].values
    
    # 构建设计矩阵X_design (添加常数项1)
    X_design = np.column_stack((np.ones(X.shape[0]), X))
    
    # 使用TensorFlow计算矩阵运算
    X_design_tf = tf.constant(X_design, dtype=tf.float32)
    y_tf = tf.constant(y.reshape(-1, 1), dtype=tf.float32)
    
    # 使用正规方程计算参数 (X^T * X)^-1 * X^T * y
    X_transpose = tf.transpose(X_design_tf)
    X_transpose_X = tf.matmul(X_transpose, X_design_tf)
    X_transpose_X_inv = tf.linalg.inv(X_transpose_X)
    X_transpose_y = tf.matmul(X_transpose, y_tf)
    
    # 计算参数 β
    beta = tf.matmul(X_transpose_X_inv, X_transpose_y)
    
    # 将TensorFlow张量转换为NumPy数组
    beta_values = beta.numpy().flatten()
    
    return beta_values

def validate_input(value, input_type, min_val, max_val):
    """验证用户输入是否有效"""
    try:
        if input_type == 'float':
            value = float(value)
        elif input_type == 'int':
            value = int(value)
            
        if value < min_val or value > max_val:
            print(f"输入必须在{min_val}和{max_val}之间")
            return None
        
        return value
    except ValueError:
        print(f"输入必须是{'数字' if input_type == 'float' else '整数'}")
        return None

def predict_price(area, rooms, model_params):
    """使用模型参数预测房价"""
    # model_params: [截距项, 面积系数, 房间数系数]
    return model_params[0] + model_params[1] * area + model_params[2] * rooms

def main():
    print("商品房价格预测系统")
    print("=" * 30)
    
    # 加载数据
    data = load_data()
    if data is None:
        print("无法加载数据，程序退出")
        return
    
    # 训练模型
    print("正在训练模型...")
    model_params = build_model(data)
    print(f"模型参数: 截距项={model_params[0]:.2f}, 面积系数={model_params[1]:.2f}, 房间数系数={model_params[2]:.2f}")
    
    # 用户交互
    while True:
        print("\n请输入商品房信息（输入'q'退出）:")
        area_input = input("房屋面积（平方米，范围20-500）: ")
        
        if area_input.lower() == 'q':
            break
        
        area = validate_input(area_input, 'float', 20, 500)
        if area is None:
            continue
        
        rooms_input = input("房间数（范围1-10）: ")
        if rooms_input.lower() == 'q':
            break
        
        rooms = validate_input(rooms_input, 'int', 1, 10)
        if rooms is None:
            continue
        
        # 预测房价
        predicted_price = predict_price(area, rooms, model_params)
        print(f"预测房价: ¥{predicted_price:.2f}万元")

if __name__ == "__main__":
    main()
